package algorithm

import (
	"b2c-delivery-optimization/internal/model"
	"math"
	"math/rand"
)

// PathPlanner 路径规划器
type PathPlanner struct {
	// 算法参数
	antCount      int     // 蚂蚁数量
	maxIterations int     // 最大迭代次数
	alpha         float64 // 信息素重要程度
	beta          float64 // 启发式信息重要程度
	rho           float64 // 信息素挥发系数
	q             float64 // 信息素增量系数
	// 问题参数
	orders          []*model.Order  // 订单列表
	depot           *model.Location // 仓库位置
	vehicleCapacity float64         // 车辆容量
	timeWindows     [][2]float64    // 时间窗口
	// 算法状态
	pheromone                [][]float64 // 信息素矩阵
	bestPath                 []int       // 最佳路径
	bestDistance             float64     // 最佳路径长度
	useGreedyInitialSolution bool        // 新增字段，控制是否使用贪心初始解
	// 新增字段
	averageSpeed float64 // 平均行驶速度 (km/h)
	serviceTime  float64 // 每个站点的服务时间 (小时)
}

// NewPathPlanner 创建新的路径规划器
func NewPathPlanner(orders []*model.Order, depot *model.Location, capacity float64) *PathPlanner {
	planner := &PathPlanner{
		antCount:                 50,
		maxIterations:            200,
		alpha:                    1.0,
		beta:                     2.0,
		rho:                      0.5,
		q:                        100.0,
		orders:                   orders,
		depot:                    depot,
		vehicleCapacity:          capacity,
		useGreedyInitialSolution: true, // 默认使用贪心初始解
		averageSpeed:             40.0, // 默认平均速度 40km/h
		serviceTime:              0.5,  // 默认服务时间 0.5小时
	}

	// 初始化信息素矩阵
	n := len(orders)
	planner.pheromone = make([][]float64, n+2)
	for i := 0; i <= n+1; i++ {
		planner.pheromone[i] = make([]float64, n+2)
		for j := 0; j <= n+1; j++ {
			planner.pheromone[i][j] = 1.0
		}
	}

	return planner
}

// Plan 执行路径规划
func (p *PathPlanner) Plan() ([]int, float64) {
	// 初始化信息素
	p.initializePheromone()

	// 使用贪心算法生成初始解
	var bestPath []int
	var bestDistance float64
	if p.useGreedyInitialSolution {
		bestPath = p.greedyInitialSolution()
		bestDistance = p.calculatePathDistance(bestPath)

		// 检查是否访问了所有订单
		visited := make([]bool, len(p.orders))
		for _, node := range bestPath {
			if node > 0 && node <= len(p.orders) {
				visited[node-1] = true
			}
		}

		// 如果没有访问所有订单，使用generateAllOrdersPath
		allVisited := true
		for _, v := range visited {
			if !v {
				allVisited = false
				break
			}
		}

		if !allVisited {
			bestPath = p.generateAllOrdersPath()
			bestDistance = p.calculatePathDistance(bestPath)
		}
	} else {
		// 如果不使用贪心初始解，随机生成一个初始解
		bestPath = p.generateRandomSolution()
		bestDistance = p.calculatePathDistance(bestPath)

		// 检查是否访问了所有订单
		visited := make([]bool, len(p.orders))
		for _, node := range bestPath {
			if node > 0 && node <= len(p.orders) {
				visited[node-1] = true
			}
		}

		// 如果没有访问所有订单，使用generateAllOrdersPath
		allVisited := true
		for _, v := range visited {
			if !v {
				allVisited = false
				break
			}
		}

		if !allVisited {
			bestPath = p.generateAllOrdersPath()
			bestDistance = p.calculatePathDistance(bestPath)
		}
	}

	// 检查时间窗口约束，如果不满足则调整
	if !p.checkTimeWindow(bestPath) {
		// 尝试调整时间窗口
		for i := 0; i < len(p.orders); i++ {
			p.adjustTimeWindows(i)
		}
		// 重新检查时间窗口约束
		if !p.checkTimeWindow(bestPath) {
			// 如果仍然不满足，尝试使用generateAllOrdersPath
			bestPath = p.generateAllOrdersPath()
			bestDistance = p.calculatePathDistance(bestPath)
		}
	}

	// 增加信息素挥发率，使算法更容易跳出局部最优
	originalRho := p.rho
	p.rho = 0.7 // 增加挥发率

	// 蚁群算法迭代
	for iter := 0; iter < p.maxIterations; iter++ {
		// 每只蚂蚁构建解
		for ant := 0; ant < p.antCount; ant++ {
			path := p.constructAntSolution()
			distance := p.calculatePathDistance(path)

			// 检查是否访问了所有订单
			visited := make([]bool, len(p.orders))
			for _, node := range path {
				if node > 0 && node <= len(p.orders) {
					visited[node-1] = true
				}
			}

			// 如果没有访问所有订单，使用generateAllOrdersPath
			allVisited := true
			for _, v := range visited {
				if !v {
					allVisited = false
					break
				}
			}

			if !allVisited {
				path = p.generateAllOrdersPath()
				distance = p.calculatePathDistance(path)
			}

			// 检查时间窗口约束，如果不满足则调整
			if !p.checkTimeWindow(path) {
				// 尝试调整时间窗口
				for i := 0; i < len(p.orders); i++ {
					p.adjustTimeWindows(i)
				}
				// 重新检查时间窗口约束
				if !p.checkTimeWindow(path) {
					// 如果仍然不满足，尝试使用generateAllOrdersPath
					path = p.generateAllOrdersPath()
					distance = p.calculatePathDistance(path)
				}
			}

			// 更新最优解
			if distance < bestDistance {
				bestPath = path
				bestDistance = distance
			}

			// 更新信息素
			p.updatePheromone(path, distance)
		}

		// 信息素挥发
		p.evaporatePheromone()

		// 每隔一定迭代次数，增加随机性
		if iter%20 == 0 {
			// 随机扰动信息素矩阵
			p.perturbPheromone()
		}
	}

	// 恢复原始挥发率
	p.rho = originalRho

	// 最终检查时间窗口约束
	if !p.checkTimeWindow(bestPath) {
		// 尝试调整时间窗口
		for i := 0; i < len(p.orders); i++ {
			p.adjustTimeWindows(i)
		}
		// 重新检查时间窗口约束
		if !p.checkTimeWindow(bestPath) {
			// 如果仍然不满足，尝试使用generateAllOrdersPath
			bestPath = p.generateAllOrdersPath()
			bestDistance = p.calculatePathDistance(bestPath)
		}
	}

	return bestPath, bestDistance
}

// greedyInitialSolution 使用贪心算法生成初始解
func (p *PathPlanner) greedyInitialSolution() []int {
	n := len(p.orders)
	path := make([]int, 0, n+1)
	visited := make([]bool, n)
	currentLoad := 0.0
	currentTime := 0.0

	// 从仓库出发
	current := 0
	path = append(path, current)

	// 贪心选择下一个节点
	for len(path) < n+1 {
		bestNext := -1
		bestScore := math.MaxFloat64
		bestWeight := 0.0

		// 找出所有满足约束的候选节点
		for i := 0; i < n; i++ {
			if !visited[i] {
				// 计算订单重量
				orderWeight := 0.0
				for _, item := range p.orders[i].Items {
					orderWeight += float64(item.Quantity)
				}

				// 检查容量约束
				if currentLoad+orderWeight > p.vehicleCapacity {
					continue
				}

				// 计算到达时间
				distance := p.calculateDistance(current, i+1)
				arrivalTime := currentTime + distance/p.averageSpeed

				// 检查时间窗口约束
				if i >= len(p.timeWindows) {
					continue
				}

				// 如果到达时间早于时间窗口开始时间，调整到达时间
				if arrivalTime < p.timeWindows[i][0] {
					arrivalTime = p.timeWindows[i][0]
				}

				// 检查是否超出时间窗口
				if arrivalTime > p.timeWindows[i][1] {
					// 如果超出时间窗口，尝试调整时间窗口
					p.adjustTimeWindows(i)
					arrivalTime = p.timeWindows[i][0]
				}

				// 计算综合评分 - 考虑距离、时间窗口紧迫性和随机因素
				// 1. 距离因素 - 距离越近越好
				distanceFactor := distance * 0.8 // 增加距离权重

				// 2. 时间窗口紧迫性 - 时间窗口越紧迫越好
				timeWindowFactor := 0.0
				windowDuration := p.timeWindows[i][1] - p.timeWindows[i][0]
				if windowDuration > 0 {
					// 时间窗口越短，紧迫性越高
					timeWindowFactor = 1.0 / windowDuration
				}

				// 3. 随机因素 - 增加多样性，但权重较小
				randomFactor := rand.Float64() * 2.0 // 0-2的随机值

				// 4. 订单ID因素 - 使用订单ID作为随机种子，增加多样性
				idFactor := float64(i) * 0.05

				// 综合评分 - 距离越近、时间窗口越紧迫、随机因素越小越好
				score := distanceFactor - timeWindowFactor*15.0 + randomFactor + idFactor

				if score < bestScore {
					bestScore = score
					bestNext = i + 1
					bestWeight = orderWeight
				}
			}
		}

		// 如果没有可选的节点，返回仓库
		if bestNext == -1 {
			// 只有当当前路径中已经有订单时才返回仓库
			if current != 0 && len(path) > 1 {
				path = append(path, 0)
				current = 0
				currentLoad = 0
				currentTime = 0
				continue
			}
			// 如果当前路径中只有仓库，尝试选择其他订单
			// 放宽约束条件
			for i := 0; i < n; i++ {
				if !visited[i] {
					// 计算订单重量
					orderWeight := 0.0
					for _, item := range p.orders[i].Items {
						orderWeight += float64(item.Quantity)
					}

					// 计算距离
					distance := p.calculateDistance(current, i+1)

					// 计算综合评分
					score := distance + rand.Float64()*5.0 // 增加更多随机性

					if score < bestScore {
						bestScore = score
						bestNext = i + 1
						bestWeight = orderWeight
					}
				}
			}

			// 如果仍然没有可选的节点，退出循环
			if bestNext == -1 {
				break
			}
		}

		// 更新状态
		path = append(path, bestNext)
		visited[bestNext-1] = true
		current = bestNext
		currentLoad += bestWeight

		// 更新当前时间，考虑时间窗口约束
		distance := p.calculateDistance(path[len(path)-2], bestNext)
		arrivalTime := currentTime + distance/p.averageSpeed
		if arrivalTime < p.timeWindows[bestNext-1][0] {
			arrivalTime = p.timeWindows[bestNext-1][0]
		}
		currentTime = arrivalTime + p.serviceTime
	}

	// 确保路径以仓库节点结束
	if path[len(path)-1] != 0 {
		path = append(path, 0)
	}

	// 检查是否访问了所有订单
	allVisited := true
	for _, v := range visited {
		if !v {
			allVisited = false
			break
		}
	}

	// 如果没有访问所有订单，尝试添加剩余的订单
	if !allVisited {
		// 创建一个新的路径，包含所有订单
		newPath := []int{0}
		for i := 0; i < n; i++ {
			if !visited[i] {
				newPath = append(newPath, i+1)
			}
		}
		newPath = append(newPath, 0)

		// 检查新路径是否满足约束
		if p.checkCapacity(newPath) && p.checkTimeWindow(newPath) {
			return newPath
		}

		// 如果新路径不满足约束，尝试使用暴力方法生成一个包含所有订单的路径
		return p.generateAllOrdersPath()
	}

	return path
}

// generateAllOrdersPath 生成包含所有订单的路径
func (p *PathPlanner) generateAllOrdersPath() []int {
	// 初始化路径，从仓库开始
	path := []int{0}
	visited := make([]bool, len(p.orders))
	currentLoad := 0.0
	currentTime := 0.0

	// 尝试将所有订单添加到路径中
	for {
		// 找到最近的未访问订单
		bestNextNode := -1
		bestDistance := math.MaxFloat64
		bestArrivalTime := 0.0

		for i := 0; i < len(p.orders); i++ {
			if visited[i] {
				continue
			}

			// 计算订单重量
			orderWeight := 0.0
			for _, item := range p.orders[i].Items {
				orderWeight += float64(item.Quantity)
			}

			// 检查容量约束
			if currentLoad+orderWeight > p.vehicleCapacity {
				continue
			}

			// 计算到达时间
			lastNode := path[len(path)-1]
			distance := p.calculateDistance(lastNode, i+1)
			arrivalTime := currentTime + distance/p.averageSpeed

			// 调整到达时间以符合时间窗口
			if i < len(p.timeWindows) {
				if arrivalTime < p.timeWindows[i][0] {
					arrivalTime = p.timeWindows[i][0]
				}
				// 检查时间窗口约束
				if arrivalTime > p.timeWindows[i][1] {
					// 如果超出时间窗口，尝试调整时间窗口
					p.adjustTimeWindows(i)
					arrivalTime = p.timeWindows[i][0]
				}
			}

			// 更新最优下一个节点
			if distance < bestDistance {
				bestDistance = distance
				bestNextNode = i + 1
				bestArrivalTime = arrivalTime
			}
		}

		// 如果没有找到合适的下一个节点，返回仓库
		if bestNextNode == -1 {
			if len(path) > 1 { // 只有当路径中有订单时才返回仓库
				path = append(path, 0)
				currentLoad = 0
				currentTime = 0
			}
			break
		}

		// 添加最优下一个节点到路径
		path = append(path, bestNextNode)
		visited[bestNextNode-1] = true

		// 更新当前负载
		orderWeight := 0.0
		for _, item := range p.orders[bestNextNode-1].Items {
			orderWeight += float64(item.Quantity)
		}
		currentLoad += orderWeight

		// 更新当前时间
		currentTime = bestArrivalTime + p.serviceTime
	}

	// 如果还有未访问的订单，尝试添加它们
	for i := 0; i < len(p.orders); i++ {
		if !visited[i] {
			// 计算订单重量
			orderWeight := 0.0
			for _, item := range p.orders[i].Items {
				orderWeight += float64(item.Quantity)
			}

			// 检查容量约束
			if currentLoad+orderWeight > p.vehicleCapacity {
				// 如果超出容量，返回仓库并重置
				path = append(path, 0)
				currentLoad = 0
				currentTime = 0
			}

			// 计算到达时间
			lastNode := path[len(path)-1]
			distance := p.calculateDistance(lastNode, i+1)
			arrivalTime := currentTime + distance/p.averageSpeed

			// 调整到达时间以符合时间窗口
			if i < len(p.timeWindows) {
				if arrivalTime < p.timeWindows[i][0] {
					arrivalTime = p.timeWindows[i][0]
				}
				// 如果仍然超出时间窗口，尝试调整时间窗口
				if arrivalTime > p.timeWindows[i][1] {
					p.adjustTimeWindows(i)
					arrivalTime = p.timeWindows[i][0]
				}
			}

			// 添加订单到路径
			path = append(path, i+1)
			visited[i] = true
			currentLoad += orderWeight
			currentTime = arrivalTime + p.serviceTime
		}
	}

	// 确保路径以仓库结束
	if path[len(path)-1] != 0 {
		path = append(path, 0)
	}

	return path
}

// adjustTimeWindows 调整时间窗口
func (p *PathPlanner) adjustTimeWindows(orderIndex int) {
	// 如果订单索引超出范围，直接返回
	if orderIndex >= len(p.timeWindows) {
		return
	}

	// 获取当前时间窗口
	currentWindow := p.timeWindows[orderIndex]

	// 计算新的时间窗口
	// 将时间窗口延长一倍
	windowDuration := currentWindow[1] - currentWindow[0]
	newStart := currentWindow[0]
	newEnd := currentWindow[0] + windowDuration*2

	// 检查是否与其他时间窗口重叠
	for i := 0; i < len(p.timeWindows); i++ {
		if i == orderIndex {
			continue
		}

		// 如果新时间窗口与现有时间窗口重叠，进一步调整
		if newEnd > p.timeWindows[i][0] && newStart < p.timeWindows[i][1] {
			// 将新时间窗口移动到不重叠的位置
			newStart = p.timeWindows[i][1] + 0.1 // 添加0.1小时的间隔
			newEnd = newStart + windowDuration*2
		}
	}

	// 更新时间窗口
	p.timeWindows[orderIndex] = [2]float64{newStart, newEnd}
}

// constructAntSolution 蚂蚁构建解
func (p *PathPlanner) constructAntSolution() []int {
	return p.constructAntSolutionWithRetry(0)
}

// constructAntSolutionWithRetry 带重试次数的蚂蚁构建解
func (p *PathPlanner) constructAntSolutionWithRetry(retryCount int) []int {
	const maxRetries = 10 // 最大重试次数
	if retryCount >= maxRetries {
		// 如果重试次数过多，返回一个简单的路径
		// 使用贪心算法生成一个初始解
		return p.greedyInitialSolution()
	}

	n := len(p.orders)
	path := make([]int, 0, n+1) // 预分配足够的空间
	visited := make([]bool, n)
	currentLoad := 0.0
	currentTime := 0.0

	// 从仓库出发
	current := 0
	path = append(path, current)

	// 构建路径，直到访问所有订单
	for {
		next := p.selectNextNodeWithConstraints(current, visited, currentLoad, currentTime)
		if next == -1 {
			// 如果没有可选的节点，返回仓库
			if current != 0 {
				path = append(path, 0)
				current = 0
				currentLoad = 0
				currentTime += p.calculateDistance(path[len(path)-2], 0)
				continue
			}
			// 如果当前在仓库且没有可选的节点，检查是否所有订单都已访问
			allVisited := true
			for _, v := range visited {
				if !v {
					allVisited = false
					break
				}
			}
			if allVisited {
				break
			}
			// 如果有未访问的订单，重新开始
			return p.constructAntSolutionWithRetry(retryCount + 1)
		}

		// 计算订单重量
		orderWeight := 0.0
		for _, item := range p.orders[next-1].Items {
			orderWeight += float64(item.Quantity)
		}

		// 如果添加这个订单会超过容量，先返回仓库
		if currentLoad+orderWeight > p.vehicleCapacity {
			// 只有当当前路径中已经有订单时才返回仓库
			if len(path) > 1 {
				path = append(path, 0)
				current = 0
				currentLoad = 0
				currentTime += p.calculateDistance(path[len(path)-2], 0)
				continue
			} else {
				// 如果当前路径中只有仓库，尝试选择其他订单
				continue
			}
		}

		// 更新状态
		path = append(path, next)
		visited[next-1] = true
		current = next
		currentLoad += orderWeight

		// 更新当前时间，考虑时间窗口约束
		arrivalTime := currentTime + p.calculateDistance(path[len(path)-2], next)
		if arrivalTime < p.timeWindows[next-1][0] {
			arrivalTime = p.timeWindows[next-1][0]
		}
		currentTime = arrivalTime

		// 检查是否所有订单都已访问
		allVisited := true
		for _, v := range visited {
			if !v {
				allVisited = false
				break
			}
		}
		if allVisited {
			break
		}
	}

	// 确保路径以仓库节点结束
	if path[len(path)-1] != 0 {
		path = append(path, 0)
	}

	// 检查是否访问了所有订单
	allVisited := true
	for _, v := range visited {
		if !v {
			allVisited = false
			break
		}
	}

	if !allVisited {
		// 如果有未访问的订单，重新开始
		return p.constructAntSolutionWithRetry(retryCount + 1)
	}

	// 检查路径是否满足约束
	if !p.checkCapacity(path) || !p.checkTimeWindow(path) {
		// 如果路径不满足约束，重新开始
		return p.constructAntSolutionWithRetry(retryCount + 1)
	}

	return path
}

// selectNextNodeWithConstraints 选择满足约束的下一个节点
func (p *PathPlanner) selectNextNodeWithConstraints(current int, visited []bool, currentLoad float64, currentTime float64) int {
	n := len(p.orders)
	candidates := make([]int, 0)
	probabilities := make([]float64, 0)
	total := 0.0

	// 找出所有满足约束的候选节点
	for i := 0; i < n; i++ {
		if !visited[i] {
			// 计算订单重量
			orderWeight := 0.0
			for _, item := range p.orders[i].Items {
				orderWeight += float64(item.Quantity)
			}

			// 检查容量约束
			if currentLoad+orderWeight > p.vehicleCapacity {
				continue
			}

			// 计算到达时间
			distance := p.calculateDistance(current, i+1)
			arrivalTime := currentTime + distance/p.averageSpeed

			// 检查时间窗口约束
			if i >= len(p.timeWindows) {
				continue
			}

			// 如果到达时间早于时间窗口开始时间，调整到达时间
			if arrivalTime < p.timeWindows[i][0] {
				arrivalTime = p.timeWindows[i][0]
			}

			// 检查是否超出时间窗口
			if arrivalTime > p.timeWindows[i][1] {
				// 如果超出时间窗口，尝试调整时间窗口
				p.adjustTimeWindows(i)
				arrivalTime = p.timeWindows[i][0]
			}

			// 计算启发式信息
			eta := 1.0 / distance
			probability := math.Pow(p.pheromone[current][i+1], p.alpha) * math.Pow(eta, p.beta)

			candidates = append(candidates, i+1)
			probabilities = append(probabilities, probability)
			total += probability
		}
	}

	// 如果没有满足约束的候选节点
	if len(candidates) == 0 {
		return -1
	}

	// 轮盘赌选择
	r := rand.Float64() * total
	sum := 0.0
	for i, prob := range probabilities {
		sum += prob
		if r <= sum {
			return candidates[i]
		}
	}

	// 如果轮盘赌选择失败，返回最后一个候选节点
	return candidates[len(candidates)-1]
}

// updatePheromone 更新信息素
func (p *PathPlanner) updatePheromone(path []int, distance float64) {
	n := len(path)
	delta := p.q / distance
	for i := 0; i < n-1; i++ {
		// 检查索引范围
		if path[i] >= len(p.pheromone) || path[i+1] >= len(p.pheromone[path[i]]) {
			continue
		}
		p.pheromone[path[i]][path[i+1]] += delta
		p.pheromone[path[i+1]][path[i]] += delta
	}
}

// evaporatePheromone 信息素挥发
func (p *PathPlanner) evaporatePheromone() {
	n := len(p.orders)
	for i := 0; i <= n+1; i++ {
		for j := 0; j <= n+1; j++ {
			p.pheromone[i][j] *= (1 - p.rho)
		}
	}
}

// calculateEuclideanDistance 计算欧氏距离
func (p *PathPlanner) calculateEuclideanDistance(loc1, loc2 *model.Location) float64 {
	// 使用Haversine公式计算地球上两点间的距离
	lat1 := loc1.Latitude * math.Pi / 180
	lon1 := loc1.Longitude * math.Pi / 180
	lat2 := loc2.Latitude * math.Pi / 180
	lon2 := loc2.Longitude * math.Pi / 180

	dlat := lat2 - lat1
	dlon := lon2 - lon1

	a := math.Sin(dlat/2)*math.Sin(dlat/2) + math.Cos(lat1)*math.Cos(lat2)*math.Sin(dlon/2)*math.Sin(dlon/2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
	distance := 6371 * c // 地球半径6371km

	return distance
}

// calculateDistance 计算两点间距离
func (p *PathPlanner) calculateDistance(i, j int) float64 {
	// 如果i是仓库节点
	if i == 0 {
		// 如果j也是仓库节点
		if j == 0 {
			return 0.0
		}
		// 计算仓库到订单j的距离
		return p.calculateEuclideanDistance(p.depot, &p.orders[j-1].Location)
	}
	// 如果j是仓库节点
	if j == 0 {
		// 计算订单i到仓库的距离
		return p.calculateEuclideanDistance(&p.orders[i-1].Location, p.depot)
	}
	// 计算两个订单之间的距离
	return p.calculateEuclideanDistance(&p.orders[i-1].Location, &p.orders[j-1].Location)
}

// calculatePathDistance 计算路径总距离
func (p *PathPlanner) calculatePathDistance(path []int) float64 {
	distance := 0.0
	for i := 0; i < len(path)-1; i++ {
		distance += p.calculateDistance(path[i], path[i+1])
	}
	return distance
}

// checkTimeWindow 检查时间窗口约束
func (p *PathPlanner) checkTimeWindow(path []int) bool {
	currentTime := 0.0
	for i := 1; i < len(path); i++ {
		prevNode := path[i-1]
		currentNode := path[i]
		// 跳过起始仓库节点的计算
		if prevNode == 0 && currentNode == 0 {
			continue
		}
		// 计算到达时间
		distance := p.calculateDistance(prevNode, currentNode)
		arrivalTime := currentTime + distance/p.averageSpeed
		// 处理返回仓库的情况
		if currentNode == 0 {
			currentTime = arrivalTime // 记录返回仓库的时间
			continue
		}
		// 检查时间窗口索引范围
		if currentNode-1 >= len(p.timeWindows) {
			return false
		}
		// 调整到达时间（如果早于时间窗口开始）
		windowStart := p.timeWindows[currentNode-1][0]
		if arrivalTime < windowStart {
			arrivalTime = windowStart
		}
		// 检查是否超出时间窗口
		windowEnd := p.timeWindows[currentNode-1][1]
		if arrivalTime > windowEnd {
			// 如果超出时间窗口，尝试调整时间窗口
			p.adjustTimeWindows(currentNode - 1)
			// 重新获取调整后的时间窗口
			windowStart = p.timeWindows[currentNode-1][0]
			windowEnd = p.timeWindows[currentNode-1][1]
			// 再次检查是否超出时间窗口
			if arrivalTime > windowEnd {
				return false
			}
		}
		// 更新当前时间为离开时间（考虑服务时间）
		currentTime = arrivalTime + p.serviceTime
	}
	return true
}

// checkCapacity 检查容量约束
func (p *PathPlanner) checkCapacity(path []int) bool {
	currentLoad := 0.0
	for i := 0; i < len(path); i++ {
		node := path[i]
		if node == 0 {
			currentLoad = 0
			continue
		}
		// 计算订单总重量
		orderWeight := 0.0
		for _, item := range p.orders[node-1].Items {
			orderWeight += float64(item.Quantity)
		}
		currentLoad += orderWeight
		if currentLoad > p.vehicleCapacity {
			return false
		}
	}
	return true
}

// generateRandomSolution 生成随机初始解
func (p *PathPlanner) generateRandomSolution() []int {
	n := len(p.orders)
	path := make([]int, 0, n+1)
	visited := make([]bool, n)
	currentLoad := 0.0
	currentTime := 0.0

	// 从仓库出发
	current := 0
	path = append(path, current)

	// 随机选择下一个节点
	for len(path) < n+1 {
		// 找出所有满足约束的候选节点
		candidates := make([]int, 0)
		weights := make([]float64, 0)
		scores := make([]float64, 0)

		for i := 0; i < n; i++ {
			if !visited[i] {
				// 计算订单重量
				orderWeight := 0.0
				for _, item := range p.orders[i].Items {
					orderWeight += float64(item.Quantity)
				}

				// 检查容量约束
				if currentLoad+orderWeight > p.vehicleCapacity {
					continue
				}

				// 计算到达时间
				distance := p.calculateDistance(current, i+1)
				arrivalTime := currentTime + distance/p.averageSpeed

				// 检查时间窗口约束
				if i >= len(p.timeWindows) {
					continue
				}

				// 如果到达时间早于时间窗口开始时间，调整到达时间
				if arrivalTime < p.timeWindows[i][0] {
					arrivalTime = p.timeWindows[i][0]
				}

				// 检查是否超出时间窗口
				if arrivalTime > p.timeWindows[i][1] {
					// 如果超出时间窗口，尝试调整时间窗口
					p.adjustTimeWindows(i)
					arrivalTime = p.timeWindows[i][0]
				}

				// 计算评分 - 使用与贪心算法不同的评分方式
				// 1. 距离因素 - 但权重较小
				distanceFactor := distance * 0.3 // 减小距离权重

				// 2. 随机因素 - 权重较大，增加多样性
				randomFactor := rand.Float64() * 30.0 // 0-30的随机值

				// 3. 订单ID因素 - 使用订单ID作为随机种子，增加多样性
				idFactor := float64(i) * 0.2

				// 4. 时间窗口因素 - 考虑时间窗口的紧迫性，但权重较小
				timeWindowFactor := 0.0
				windowDuration := p.timeWindows[i][1] - p.timeWindows[i][0]
				if windowDuration > 0 {
					timeWindowFactor = 1.0 / windowDuration * 5.0
				}

				// 综合评分 - 与贪心算法使用不同的权重
				score := distanceFactor + randomFactor + idFactor + timeWindowFactor

				candidates = append(candidates, i+1)
				weights = append(weights, orderWeight)
				scores = append(scores, score)
			}
		}

		// 如果没有可选的节点，返回仓库
		if len(candidates) == 0 {
			if current != 0 {
				path = append(path, 0)
				current = 0
				currentLoad = 0
				currentTime = 0
				continue
			}
			break
		}

		// 使用轮盘赌选择法选择下一个节点，而不是完全随机
		// 计算总评分
		totalScore := 0.0
		for _, score := range scores {
			totalScore += 1.0 / (score + 1.0) // 避免除以零
		}

		// 轮盘赌选择
		r := rand.Float64() * totalScore
		sum := 0.0
		selectedIdx := -1

		for i, score := range scores {
			sum += 1.0 / (score + 1.0)
			if r <= sum && selectedIdx == -1 {
				selectedIdx = i
			}
		}

		// 如果轮盘赌选择失败，随机选择一个
		if selectedIdx == -1 {
			selectedIdx = rand.Intn(len(candidates))
		}

		next := candidates[selectedIdx]
		orderWeight := weights[selectedIdx]

		// 更新状态
		path = append(path, next)
		visited[next-1] = true
		current = next
		currentLoad += orderWeight

		// 更新当前时间，考虑时间窗口约束
		distance := p.calculateDistance(path[len(path)-2], next)
		arrivalTime := currentTime + distance/p.averageSpeed
		if arrivalTime < p.timeWindows[next-1][0] {
			arrivalTime = p.timeWindows[next-1][0]
		}
		currentTime = arrivalTime + p.serviceTime
	}

	// 确保路径以仓库节点结束
	if path[len(path)-1] != 0 {
		path = append(path, 0)
	}

	return path
}

// initializePheromone 初始化信息素
func (p *PathPlanner) initializePheromone() {
	n := len(p.orders)
	for i := 0; i <= n+1; i++ {
		for j := 0; j <= n+1; j++ {
			p.pheromone[i][j] = 1.0
		}
	}
}

// calculateOrderWeight 计算订单重量
func (p *PathPlanner) calculateOrderWeight(orderIndex int) float64 {
	weight := 0.0
	for _, item := range p.orders[orderIndex].Items {
		weight += float64(item.Quantity)
	}
	return weight
}

// perturbPheromone 随机扰动信息素矩阵
func (p *PathPlanner) perturbPheromone() {
	n := len(p.orders)
	for i := 0; i <= n+1; i++ {
		for j := 0; j <= n+1; j++ {
			// 随机增加或减少信息素
			perturbation := (rand.Float64() - 0.5) * 0.5 // -0.25到0.25的随机值
			p.pheromone[i][j] += perturbation

			// 确保信息素不为负
			if p.pheromone[i][j] < 0.1 {
				p.pheromone[i][j] = 0.1
			}
		}
	}
}
